<?php
/**
 * @Name : MPE 应用控制
 * @Function : 提供MPE 创建，启动，停止及删除功能
 *     服务涉及对应用一、二级域名映射操作，初始管理员操作和应用对应SAAS中心的配置参数操作
 * @Author : Haiwera
 * @Created : 2016-11-07
 * @Copyright : Haiwera.Fiidee.Monda.Cn
 */
namespace api\service;

use api\service\interfaces\IAppService;
use herosphp\core\Loader;
use herosphp\utils\AjaxResult;
use herosphp\bean\Beans;
use herosphp\core\Log;
use herosphp\string\StringUtils;
use herosphp\utils\ArrayUtils;


Loader::import('api.service.interfaces.IAppService');

class MpeService implements IAppService
{

    private $__configService;
    private $__adminService;
    private $__instancesConfigFile;
    //所有MPE应用实例的域名映射
    // 注：该文件由于每次请求都会引入 ，为加快对域名检索的速度，
    // 若一个应用有多个域名时 ， 会在映射表中存在多条记录
    // 在对域表映射表操作时要注意
    private $__instances;

    private $_clone_app_id = 'b21a585cd1660179716492bc';//克隆对象appid


    public function __construct()
    {

        //域名映射文件
        $this->__instancesConfigFile = APP_PATH . '/configs/instances.config.php';
        if (!is_writable($this->__instancesConfigFile)) {
            throw new \Exception($this->__instancesConfigFile . ' 不可写 !');
        }
        $this->__instances = include $this->__instancesConfigFile;
        $this->__configService = Beans::get('admin.adminSetting.service');
        $this->__adminService = Beans::get('admin.adminManager.service');

    }

    public function __destruct()
    {
        file_put_contents($this->__instancesConfigFile, "<?php return " . var_export($this->__instances, true) . ';');
    }

    //设置saas配置信息到数据库
    public function setSaasConfigs($data)
    {
        return $this->__configService->setConfigs(array(
            'saas_domain' => $data['domain'],
            'saas_level2_domain' => $data['level2_domain'],
            'saas_status' => $data['status'],
            'saas_start_time' => $data['start_time'],
            'saas_end_time' => $data['end_time'] ? $data['end_time'] : '',
            'saas_addtime' => date('Y-m-d H:i:s'),
            'saas_edittime' => date('Y-m-d H:i:s'),
        ));
    }

    //删除saas配置
    public function delSaasConfigs()
    {
        return $this->__configService->deleteConfigs(array(
            'saas_domain',
            'saas_level2_domain',
            'saas_status',
            'saas_start_time',
            'saas_end_time',
            'saas_addtime',
            'saas_edittime',
        ));
    }

    /**
     * 根据appid获取instances_config.php文件中的匹配域名，
     * 并用形如array('1'=>'mep.com','2'=>'mpe.dasu123.com')数组返回,
     * 其中的键值1和2代表一级域名和二级域名
     * @param $appid
     * @return array
     */
    public function getKeyByAppids($appid)
    {
        $keyArr = array();
        foreach ($this->__instances as $k => $v) {
            if ($v['app_id'] == $appid) {
                $keyArr[$v['domain_level']] = $k;
            }
        }
        return $keyArr;
    }

    /**
     * 返回数据
     * @param $bool 状态 成功=true,失败=false
     * @param $message
     */
    private function returnM($bool, $message)
    {
        return $bool ? new AjaxResult(AjaxResult::OP_SUCCESS, $message) : new AjaxResult(AjaxResult::OP_FAILURE, $message);
    }

    /**
     * 注册服务
     * @param $data array(
     *  mpeid : MPEID  对应 MPE系统的appId
     *  domain : 域名
     *  level2_domain : 二级域名
     *  status : 是否立即开通
     *  admin_user :
     *  admin_pass :
     *  start_time :
     *  end_time :
     * )
     * @return mixed
     */

    public function create($data)
    {
        if (!$data['domain'] && !$data['level2_domain']) {
            return $this->returnM(false, L('API_NO_DOMAIN'));
        }

        if (!$data['mpeid']) {
            return $this->returnM(false, L('API_NO_MPE_ID'));

        }

        $data['level2_domain'] = $data['level2_domain'] . '.' . C('mpe_domain');

        $data['site_url'] = 'http://' . $data['level2_domain'];

        !defined('__APP_ID__') && define('__APP_ID__', $data['mpeid']);

        if (!$this->setSaasConfigs($data)) {

            return $this->returnM(false, L('API_APP_DB_ERROR'));
        }

        $admin = array(
            'username' => $data['admin_user'],
            'password' => passwd($data['admin_pass']),
            'mobile' => '',
            'jobno' => '',
            'email' => '',
            'name' => $data['admin_user'],
            'role_id' => 0,
            'last_login_ip' => 0,
            'status' => 1,
            'addtime' => date('Y-m-d H:i:s'),
            'updatetime' => date('Y-m-d H:i:s'),
            'app_id' => $data['mpeid'],
            'last_login_time' => date('Y-m-d H:i:s')
        );
        $new_manager_id=$this->__adminService->add($admin);
        if (!$new_manager_id) {

            return $this->returnM(false, L('API_APP_ADD_ADMIN_FAILED'));

        }
        if ($data['domain']) {
            $this->__instances[$data['domain']] = array(
                'app_id' => $data['mpeid'],
                'status' => $data['status'],
                'domain_level' => 1,
                'start_time' => $data['start_time'],
                'end_time' => $data['end_time'],
            );
        }
        if ($data['level2_domain']) {
            $this->__instances[$data['level2_domain']] = array(
                'app_id' => $data['mpeid'],
                'status' => $data['status'],
                'domain_level' => 2,
                'start_time' => $data['start_time'],
                'end_time' => $data['end_time'],
            );
        }

        $this->cloneAll($data['mpeid'],$new_manager_id);

        //$this->_adPlaceAndFLConfigs($data['mpeid']);

        return $this->returnM(true, L('API_APP_CREATE_SUCCESS'));

    }

    /**
     * 更新应用 by Yu
     * @param $data
     * @param mpeid : MPEID  对应 MPE系统的appId
     */
    public function update($data, $mpeid)
    {
        //Log::info(array($data, $mpeid));

        (!defined('__APP_ID__')) && define('__APP_ID__', $mpeid);

        //根据appid获取instances_config.php文件中的匹配域名
        $levelToDomainArr = $this->getKeyByAppids($mpeid);//array('1'=>'mep.com','2'=>'mpe.dasu123.com')数组返回

        $levelToKeyArr = array(1 => 'domain', 2 => 'level2_domain');


        if (!$levelToDomainArr) {//不存在该app的配置

            return $this->returnM(false, L('API_APP_NOT_FOUND'));
        }
        //拼接app.config.php中的主域和post过来的二级域名前缀
        $data['level2_domain'] = $data['level2_domain'] . '.' . C('mpe_domain');

        $data['site_url'] = 'http://' . $data['level2_domain'];

        foreach ($levelToDomainArr as $level => $domain) {

            if (isset($domain)) {

                //获取原来的status
                $tmpStatus = $this->__instances[$levelToDomainArr[$level]]['status'];

                //如果instances_config.php文件中的域名和要修改的域名不一致，就删掉这个数组,等待重建
                if ($data[$levelToKeyArr[$level]] != $levelToDomainArr[$level]) {

                    unset($this->__instances[$levelToDomainArr[$level]]);
                }
                //重建数组
                $this->__instances[$data[$levelToKeyArr[$level]]] = array(
                    'app_id' => $mpeid,
                    'status' => $tmpStatus,
                    'domain_level' => $level,
                    'start_time' => $data['start_time'],
                    'end_time' => $data['end_time'],
                );

            }

        }

        $settings = array();
        foreach ($data as $k => $v) {
            $settings['saas_' . $k] = $v;
        }
        $settings['saas_edittime'] = date('Y-m-d H:i:s');
        if (!$this->__configService->setConfigs($settings)) {
            return $this->returnM(false, L('API_APP_DB_ERROR'));

        }

        //修改初始管理员密码
        if ($data['admin_pass'] != '') {

            $admin = array(
                'password' => passwd($data['admin_pass']),
                'updatetime' => date('Y-m-d H:i:s'),
            );

            if (!$this->__adminService->updates($admin, array('app_id' => $mpeid, 'username' => $data['admin_user']))) {

                return $this->returnM(false, "管理员{$data['admin_user']}无法找到");
            }
        }


        return $this->returnM(true, L('API_APP_UPDATE_SUCCESS'));

    }

    /**
     * 开通应用
     * @param mpeid : MPEID  对应 MPE系统的appId
     */
    public function start($mpeid)
    {
        if (!$mpeid) {
            return $this->returnM(false, L('API_NO_MPE_ID'));

        }
        foreach ($this->__instances as $k => $v) {
            if ($v['app_id'] == $mpeid) {
                $this->__instances[$k]['status'] = 1;
            }
        }

        !defined('__APP_ID__') && define('__APP_ID__', $mpeid);

        $this->__configService->setConfigs(array(
            'saas_status' => 1,
            'saas_edittime' => date('Y-m-d H:i:s'),
        ));
        return $this->returnM(true, L('API_APP_START_SUCCESS'));

    }

    /**
     * 关闭应用
     * @param mpeid : MPEID  对应 MPE系统的appId
     */
    public function stop($mpeid)
    {
        if (!$mpeid) {
            return $this->returnM(false, L('API_NO_MPE_ID'));
        }
        foreach ($this->__instances as $k => $v) {
            if ($v['app_id'] == $mpeid) {
                $this->__instances[$k]['status'] = 0;
            }
        }
        !defined('__APP_ID__') && define('__APP_ID__', $mpeid);

        $this->__configService->setConfigs(array(
            'saas_status' => 0,
            'saas_edittime' => date('Y-m-d H:i:s'),
        ));
        return $this->returnM(true, L('API_APP_STOP_SUCCESS'));

    }

    /**
     * 删除应用
     * @param mpeid : MPEID  对应 MPE系统的appId
     */
    public function delete($mpeid)
    {
        if (!$mpeid) {
            return $this->returnM(false, L('API_NO_MPE_ID'));

        }

        !defined('__APP_ID__') && define('__APP_ID__', $mpeid);

        if (!$this->delSaasConfigs()) {

            return $this->returnM(false, L('API_APP_DB_ERROR'));

        }
        if (!$this->__adminService->deletes(array('app_id' => $mpeid))) {
            return $this->returnM(false, L('API_APP_DB_ERROR'));
        }
        foreach ($this->__instances as $k => $v) {
            if ($v['app_id'] == $mpeid) {
                unset($this->__instances[$k]);
            }
        }
        return $this->returnM(true, L('API_APP_DELETE_SUCCESS'));

    }

    /**
     * 克隆应用
     * @param $new_app_id 新的app_id
     * @param $manager_id 管理员id
     */
    public function cloneAll($new_app_id,$manager_id)
    {


        $clone_app_id = $this->_clone_app_id;

        $this->cloneByInformation($clone_app_id,$new_app_id,$manager_id);//克隆资讯

        $this->cloneByInformationNotice($clone_app_id,$new_app_id,$manager_id);//克隆公告

        $this->cloneByInformationAd($clone_app_id,$new_app_id,$manager_id);//克隆广告
        $this->cloneByInformationSinglepage($clone_app_id,$new_app_id,$manager_id);//克隆单页
        $this->cloneByMessageRemind($clone_app_id,$new_app_id,$manager_id);//克隆提醒
        $this->cloneBySettingFriendlink($clone_app_id, $new_app_id,$manager_id);//克隆友情链接

        $this->cloneByProduct($clone_app_id,$new_app_id,$manager_id);//克隆商品
        $this->cloneByNav($clone_app_id,$new_app_id,$manager_id);


    }


    /**
     * 克隆information 资讯
     * @param $clone_app_id
     * @param $new_app_id
     */
    public function cloneByInformation($clone_app_id, $new_app_id,$manager_id)
    {
        $informationCateModel = Loader::model('InformationCate');
        $informationDataModel = Loader::model('InformationData');
        $informationModel = Loader::model('Information');
        $informationTagsModel = Loader::model('InformationTags');


        $sql = "Select i.*,id.content As id_content, ic.id As ic_id,ic.name As ic_name,ic.parent_id As ic_parent_id,ic.summary As ic_summary,ic.manager_id As ic_manager_id,ic.sort_index As ic_sort_index From information As i
              Left Join information_cate As ic On i.cate_id=ic.id
              Left Join information_data As id On i.id=id.id
              Where i.app_id='{$clone_app_id}'";

        $items = $informationModel->getDB()->excute($sql)->fetchAll($fetch_style = 2);

        foreach ($items as $k => $item) {


            $informationModel->beginTransaction();

            $informationCateArray = array(
                'name' => $item['ic_name'],
                'parent_id' => $item['ic_parent_id'],
                'summary' => $item['ic_summary'],
                'manager_id' => $manager_id,
                'app_id' => $new_app_id,
                'sort_index' => $item['ic_sort_index'],
            );
            $selectItem1 = $informationCateModel->getItem(array('name'=>$informationCateArray['name'],'app_id' => $informationCateArray['app_id']));
            $information_cate_id = $selectItem1 ? $selectItem1['id'] : $informationCateModel->add($informationCateArray);


            $informationArray = array(
                'id' => StringUtils::genGlobalUid(),
                'title' => $item['title'],
                'image_url' => $item['image_url'],
                'cate_id' => $information_cate_id,
                'summary' => $item['summary'],
                'author' => $item['author'],
                'addtime' => $item['addtime'],
                'manager_id' => $manager_id,
                'app_id' => $new_app_id,
                'source' => $item['source'],
                'source_link' => $item['source_link'],
                'is_jump_link' => $item['is_jump_link'],
                'release_status' => $item['release_status'],
                'is_recommend' => $item['is_recommend'],
                'views' => $item['views'],
                'tags' => $item['tags'],
            );

            $tmp2=array('title'=>$informationArray['title'],'image_url'=>$informationArray['image_url'],'cate_id'=>$informationArray['cate_id'],'app_id' => $informationArray['app_id']);

            $selectItem2 = $informationModel->getItem($tmp2);

            $information_id = $selectItem2 ? $selectItem2['id'] : $informationModel->add($informationArray);

            $informationDataArray = array(
                'id' => $information_id,
                'content' => $item['id_content'],
            );

            $selectItem3 = $informationDataModel->getItem(array('id'=>$information_id));

            $informationData_id = $selectItem3 ? $selectItem3['id'] : $informationDataModel->add($informationDataArray);

            if ($information_cate_id && $information_id && $informationData_id) {

                $informationModel->commit();
            } else {

                $informationModel->rollback();

            }
        }

    }

    /**
     * 克隆information_notice 公告
     *
     * @param $clone_app_id
     * @param $new_app_id
     */
    public function cloneByInformationNotice($clone_app_id, $new_app_id,$manager_id)
    {

        $informationNoticeCateModel = Loader::model('InformationNoticeCate');
        $informationNoticeModel = Loader::model('InformationNotice');


        $items = $this->selectData($informationNoticeModel, $informationNoticeCateModel, 'cate_id', $clone_app_id);

        foreach ($items as $k => $item) {

            $this->cloneRelationData($informationNoticeModel, $informationNoticeCateModel, 'cate_id', $new_app_id,$item,$manager_id);
        }

    }

    /**
     * 克隆information_ad 广告
     *
     * @param $clone_app_id
     * @param $new_app_id
     */
    public function cloneByInformationAd($clone_app_id, $new_app_id,$manager_id)
    {

        $informationAdPlaceModel = Loader::model('informationAdPlace');
        $informationAdModel = Loader::model('informationAd');

        $sql = "Select ad.*,adp.title As adp_title, adp.key As adp_key,adp.summary As adp_summary, adp.width As adp_width,adp.height As adp_height ,adp.cate As adp_cate ,adp.default_type As adp_default_type ,adp.default_content As adp_default_content,adp.status As adp_status ,adp.manager_id As adp_manager_id From information_ad As ad
              Left Join information_ad_place As adp On adp.key=ad.ad_place_key And adp.app_id=ad.app_id
              Where ad.app_id='{$clone_app_id}'";

        $items = $informationAdModel->getDB()->excute($sql)->fetchAll($fetch_style = 2);

        foreach ($items as $k => $item) {

            $informationAdModel->beginTransaction();

            $informationAdPlaceArray = array(
                'title' => $item['adp_title'],
                'key' => $item['adp_key'],
                'summary' => $item['adp_summary'],
                'width' => $item['adp_width'],
                'height' => $item['adp_height'],
                'cate' => $item['adp_cate'],
                'default_type' => $item['adp_default_type'],
                'default_content' => $item['adp_default_content'],
                'status' => $item['adp_status'],
                'manager_id' => $manager_id,
                'app_id' => $new_app_id,
            );

            $tmp2=array('title'=>$informationAdPlaceArray['title'],'key'=>$informationAdPlaceArray['key'],'cate'=>$informationAdPlaceArray['cate'],'app_id' => $informationAdPlaceArray['app_id']);

            $selectItem1 = $informationAdPlaceModel->getItem($tmp2);

            $informationAdPlace_id = $selectItem1 ? $selectItem1['id'] : $informationAdPlaceModel->add($informationAdPlaceArray);


            $informationAdArray = array(
                'ad_place_key' => $item['ad_place_key'],
                'title' => $item['title'],
                'content' => $item['content'],
                'summary' => $item['summary'],
                'link' => $item['link'],
                'target' => $item['target'],
                'addtime' => $item['addtime'],
                'endtime' => $item['endtime'],
                'manager_id' => $manager_id,
                'app_id' => $new_app_id,

            );
            $tmp3=array('title'=>$informationAdArray['title'],'ad_place_key'=>$informationAdArray['ad_place_key'],'app_id' => $informationAdArray['app_id']);

            $selectItem2 = $informationAdModel->getItem($tmp3);
            $informationAd_id = $selectItem2 ? $selectItem2['id'] : $informationAdModel->add($informationAdArray);

            if ($informationAdPlace_id > 0 && $informationAd_id > 0) {

                $informationAdModel->commit();
            } else {

                $informationAdModel->rollback();

            }
        }

    }

    /**
     * 克隆information_singlepage 单页
     *
     * @param $clone_app_id
     * @param $new_app_id
     */
    public function cloneByInformationSinglepage($clone_app_id, $new_app_id,$manager_id)
    {

        $informationSinglepageCateModel = Loader::model('InformationSinglepageCate');

        $informationSinglepageModel = Loader::model('InformationSinglepage');

        $items = $this->selectData($informationSinglepageModel, $informationSinglepageCateModel, 'cate_id', $clone_app_id);

        foreach ($items as $k => $item) {

            $this->cloneRelationData($informationSinglepageModel, $informationSinglepageCateModel, 'cate_id', $new_app_id,$item,$manager_id);

        }

    }

    /**
     * 克隆message_remind 提醒模板、规则
     *
     * @param $clone_app_id
     * @param $new_app_id
     */
    public function cloneByMessageRemind($clone_app_id, $new_app_id,$manager_id)
    {

        $messageRemindRuleModel = Loader::model('MessageRemindRule');

        $messageRemindTmplModel = Loader::model('MessageRemindTmpl');

        $items = $this->selectData($messageRemindRuleModel, $messageRemindTmplModel, 'tmpl_id', $clone_app_id);

        foreach ($items as $k => $item) {

            $this->cloneRelationData($messageRemindRuleModel, $messageRemindTmplModel, 'tmpl_id', $new_app_id,$item,$manager_id);

        }

    }
    /**
     * 克隆 admin_nav 导航栏
     * @param $clone_app_id
     * @param $new_app_id
     */
    public function cloneByNav($clone_app_id, $new_app_id)
    {
        $navModel = Loader::model('InformationSinglepageCate');
        $items = $navModel->getItem(array('app_id'=>$clone_app_id,'is_default'=>1));
        if($items)
        {
            foreach($items as $item)
            {
                $data = array(
                    'name'      =>  $item['name'],
                    'url'       =>  $item['url'],
                    'addtime'   =>  date('Y-m-d H:i:s'),
                    'edittime'  =>  date('Y-m-d H:i:s'),
                    'display'   =>  1,
                    'blank'     =>  0,
                    'manager_id'=>  0,
                    'app_id'    =>  $new_app_id,
                    'listorder' =>  $item['listorder'],
                    'is_default'=>  1,
                );
                $navModel->add($data);
            }
        }

    }

    /**
     * 克隆setting_friend_link 友情链接
     *
     * @param $clone_app_id
     * @param $new_app_id
     */
    public function cloneBySettingFriendlink($clone_app_id, $new_app_id,$manager_id)
    {

        $settingFriendlinkModel = Loader::model('SettingFriendlink');

        $settingFriendlinkCateModel = Loader::model('SettingFriendlinkCate');

        $items = $this->selectData($settingFriendlinkModel, $settingFriendlinkCateModel, 'catid', $clone_app_id);

        foreach ($items as $k => $item) {

            $this->cloneRelationData($settingFriendlinkModel, $settingFriendlinkCateModel, 'catid', $new_app_id,$item,$manager_id);

        }

    }

    /**
     * 克隆product 商品
     *
     * @param $clone_app_id
     * @param $new_app_id
     */
    public function cloneByProduct($clone_app_id, $new_app_id,$manager_id)
    {

        $productModel = Loader::model('product');

        $repertoryModel = Loader::model('repertory');

        $items = $this->selectData($productModel, $repertoryModel, 'repertory_id', $clone_app_id);

        foreach ($items as $k => $item) {
            $this->cloneRelationData($productModel, $repertoryModel, 'repertory_id', $new_app_id,$item,$manager_id);

        }

    }

    /**
     * 两表相连获取数组
     * @param $primaryModel 主表
     * @param $foreignModel 外表
     * @param $foreign_key 外键
     * @param $app_id
     * @return mixed
     */
    public function selectData($primaryModel, $foreignModel, $foreign_key, $app_id)
    {

        $items = $primaryModel->getItems(array('app_id' => $app_id));
        $newItems = array();
        if (!empty($items)) {
            $ids = array();
            foreach ($items as $val) {
                $ids[] = $val[$foreign_key];
            }
            $foreigns = $foreignModel->getItems(array('app_id' => $app_id, 'id' => array('$in' => $ids)));
            $foreigns = ArrayUtils::changeArrayKey($foreigns, 'id');
            foreach ($items as $key => $value) {

                $newItems[] = array('p' => $value, 'f' => $foreigns[$value[$foreign_key]]);

            }
        }

        return $newItems;
    }

    /**
     * 克隆关联表数据
     * @param $primaryModel
     * @param $foreignModel
     * @param $foreign_key
     * @param $new_app_id
     */
    public function cloneRelationData($primaryModel, $foreignModel, $foreign_key, $new_app_id,$item,$manager_id){

        $primaryModel->beginTransaction();

        $item['f']['app_id'] = $new_app_id;

        unset($item['f']['id']);
        unset($item['f']['manager_id']);

        $selectItem1 = $foreignModel->getItem($item['f']);

        $item['f']['manager_id'] = $manager_id;

        $item['p'][$foreign_key] = $selectItem1 ? $selectItem1['id'] : $foreignModel->add($item['f']);

        $item['p']['app_id'] = $new_app_id;

        unset($item['p']['id']);

        if(isset($item['p']['addtime'])){
            unset($item['p']['addtime']);
        }
        if(isset($item['p']['edittime'])){
            unset($item['p']['edittime']);
        }
        if(isset($item['p']['updatetime'])){
            unset($item['p']['updatetime']);
        }
        if(isset($item['p']['manager_id'])){
            unset($item['p']['manager_id']);
        }

        $selectItem2 = $primaryModel->getItem($item['p']);

        $item['p']['manager_id'] = $manager_id;

        $newId = $selectItem2 ? $selectItem2['id'] : $primaryModel->add($item['p']);

        if ($item['p'][$foreign_key] && $newId) {

            $primaryModel->commit();
        } else {

            $primaryModel->rollback();
        }

    }

}
